home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gas / gassrc04.zoo / sparc.c < prev    next >
C/C++ Source or Header  |  1991-01-24  |  27KB  |  1,286 lines

  1. /* sparc.c -- Assemble for the SPARC
  2.    Copyright (C) 1989 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. #include <stdio.h>
  22. #include <ctype.h>
  23.  
  24. #include "sparc-opcode.h"
  25. #include "as.h"
  26. #include "frags.h"
  27. #include "struc-symbol.h"
  28. #include "flonum.h"
  29. #include "expr.h"
  30. #include "hash.h"
  31. #include "md.h"
  32. #include "sparc.h"
  33. #include "write.h"
  34. #include "read.h"
  35. #include "symbols.h"
  36.  
  37. void md_begin();
  38. void md_end();
  39. void md_number_to_chars();
  40. void md_assemble();
  41. char *md_atof();
  42. void md_convert_frag();
  43. void md_create_short_jump();
  44. void md_create_long_jump();
  45. int  md_estimate_size_before_relax();
  46. void md_number_to_imm();
  47. void md_number_to_disp();
  48. void md_number_to_field();
  49. void md_ri_to_chars();
  50. void emit_relocations();
  51. static void sparc_ip();
  52.  
  53. const relax_typeS md_relax_table[] = { 0 };
  54.  
  55. /* handle of the OPCODE hash table */
  56. static struct hash_control *op_hash = NULL;
  57.  
  58. static void s_seg(), s_proc(), s_data1(), s_reserve(), s_common();
  59. extern void s_globl(), s_long(), s_short(), s_space(), cons();
  60.  
  61. const pseudo_typeS
  62. md_pseudo_table[] = {
  63.     { "common",     s_common,   0 },
  64.     { "global",     s_globl,    0 },
  65.     { "half",       cons,       2 },
  66.     { "proc",       s_proc,     0 },
  67.     { "reserve",    s_reserve,  0 },
  68.     { "seg",        s_seg,      0 },
  69.     { "skip",       s_space,    0 },
  70.     { "word",       cons,       4 },
  71.     { NULL,         0,          0 },
  72. };
  73.  
  74. int md_short_jump_size = 4;
  75. int md_long_jump_size = 4;
  76. int omagic  =  (0x103 << 16) | OMAGIC;  /* Magic number for header */
  77.  
  78. /* This array holds the chars that always start a comment.  If the
  79.     pre-processor is disabled, these aren't very useful */
  80. char comment_chars[] = "!";    /* JF removed '|' from comment_chars */
  81.  
  82. /* This array holds the chars that only start a comment at the beginning of
  83.    a line.  If the line seems to have the form '# 123 filename'
  84.    .line and .file directives will appear in the pre-processed output */
  85. /* Note that input_file.c hand checks for '#' at the beginning of the
  86.    first line of the input file.  This is because the compiler outputs
  87.    #NO_APP at the beginning of its output. */
  88. /* Also note that '/*' will always start a comment */
  89. char line_comment_chars[] = "#";
  90.  
  91. /* Chars that can be used to separate mant from exp in floating point nums */
  92. char EXP_CHARS[] = "eE";
  93.  
  94. /* Chars that mean this number is a floating point constant */
  95. /* As in 0f12.456 */
  96. /* or    0d1.2345e12 */
  97. char FLT_CHARS[] = "rRsSfFdDxXpP";
  98.  
  99. /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
  100.    changed in read.c .  Ideally it shouldn't have to know about it at all,
  101.    but nothing is ideal around here.
  102.  */
  103. int size_reloc_info = sizeof(struct reloc_info_sparc);
  104.  
  105. static unsigned char octal[256];
  106. #define isoctal(c)  octal[c]
  107. static unsigned char toHex[256];
  108.  
  109. /*
  110.  *  anull bit - causes the branch delay slot instructions to not be executed 
  111.  */
  112. #define ANNUL       (1 << 29)
  113.  
  114. struct sparc_it {
  115.     char    *error;
  116.     unsigned long opcode;
  117.     struct nlist *nlistp;
  118.     expressionS exp;
  119.     int pcrel;
  120.     enum reloc_type reloc;
  121. } the_insn, set_insn;
  122.  
  123. #ifdef __STDC__
  124. #if 0
  125. static void print_insn(struct sparc_it *insn);
  126. #endif
  127. static int getExpression(char *str);
  128. #else
  129. #if 0
  130. static void print_insn();
  131. #endif
  132. static int getExpression();
  133. #endif
  134. static char *expr_end;
  135. static int special_case;
  136.  
  137. #define SPECIAL_CASE_SET    1
  138.  
  139. /*
  140.  * sort of like s_lcomm
  141.  *
  142.  */
  143. static void
  144. s_reserve()
  145. {
  146.     char *name;
  147.     char c;
  148.     char *p;
  149.     int temp;
  150.     symbolS *symbolP;
  151.  
  152.     name = input_line_pointer;
  153.     c = get_symbol_end();
  154.     p = input_line_pointer;
  155.     *p = c;
  156.     SKIP_WHITESPACE();
  157.     if ( * input_line_pointer != ',' ) {
  158.     as_warn("Expected comma after name");
  159.     ignore_rest_of_line();
  160.     return;
  161.     }
  162.     input_line_pointer ++;
  163.     if ((temp = get_absolute_expression()) < 0) {
  164.     as_warn("BSS length (%d.) <0! Ignored.", temp);
  165.     ignore_rest_of_line();
  166.     return;
  167.     }
  168.     *p = 0;
  169.     symbolP = symbol_find_or_make(name);
  170.     *p = c;
  171.     if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) {
  172.     as_warn("bad .reserve segment: `%s'", input_line_pointer);
  173.     return;
  174.     }
  175.     input_line_pointer += 6;
  176.     if (symbolP->sy_other == 0 
  177.         && symbolP->sy_desc  == 0
  178.     && ((symbolP->sy_type  == N_BSS
  179.     && symbolP->sy_value == local_bss_counter)
  180.     || ((symbolP->sy_type & N_TYPE) == N_UNDF
  181.     && symbolP->sy_value == 0))) {
  182.         symbolP->sy_value = local_bss_counter;
  183.         symbolP->sy_type  = N_BSS;
  184.         symbolP->sy_frag  = & bss_address_frag;
  185.         local_bss_counter += temp;
  186.     } else {
  187.     as_warn( "Ignoring attempt to re-define symbol from %d. to %d.",
  188.         symbolP->sy_value, local_bss_counter );
  189.     }
  190.     demand_empty_rest_of_line();
  191.     return;
  192. }
  193.  
  194. static void
  195. s_common()
  196. {
  197.     register char *name;
  198.     register char c;
  199.     register char *p;
  200.     register int temp;
  201.     register symbolS *    symbolP;
  202.  
  203.     name = input_line_pointer;
  204.     c = get_symbol_end();
  205.     /* just after name is now '\0' */
  206.     p = input_line_pointer;
  207.     *p = c;
  208.     SKIP_WHITESPACE();
  209.     if ( * input_line_pointer != ',' ) {
  210.     as_warn("Expected comma after symbol-name");
  211.     ignore_rest_of_line();
  212.     return;
  213.     }
  214.     input_line_pointer ++; /* skip ',' */
  215.     if ( (temp = get_absolute_expression ()) < 0 ) {
  216.     as_warn(".COMMon length (%d.) <0! Ignored.", temp);
  217.     ignore_rest_of_line();
  218.     return;
  219.     }
  220.     *p = 0;
  221.     symbolP = symbol_find_or_make (name);
  222.     *p = c;
  223.     if (   (symbolP->sy_type & N_TYPE) != N_UNDF ||
  224.         symbolP->sy_other != 0 || symbolP->sy_desc != 0) {
  225.     as_warn( "Ignoring attempt to re-define symbol");
  226.     ignore_rest_of_line();
  227.     return;
  228.     }
  229.     if (symbolP->sy_value) {
  230.     if (symbolP->sy_value != temp) {
  231.         as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.",
  232.         symbolP->sy_name, symbolP->sy_value, temp);
  233.     }
  234.     } else {
  235.     symbolP->sy_value = temp;
  236.     symbolP->sy_type |= N_EXT;
  237.     }
  238.     know(symbolP->sy_frag == &zero_address_frag);
  239.     if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) {
  240.     p=input_line_pointer;
  241.     while(*p && *p!='\n')
  242.         p++;
  243.     c= *p;
  244.     *p='\0';
  245.     as_warn("bad .common segment: `%s'", input_line_pointer);
  246.     *p=c;
  247.     return;
  248.     }
  249.     input_line_pointer += 6;
  250.     demand_empty_rest_of_line();
  251.     return;
  252. }
  253.  
  254. static void
  255. s_seg()
  256. {
  257.  
  258.     if (strncmp(input_line_pointer, "\"text\"", 6) == 0) {
  259.     input_line_pointer += 6;
  260.     s_text();
  261.     return;
  262.     }
  263.     if (strncmp(input_line_pointer, "\"data\"", 6) == 0) {
  264.     input_line_pointer += 6;
  265.     s_data();
  266.     return;
  267.     }
  268.     if (strncmp(input_line_pointer, "\"data1\"", 7) == 0) {
  269.     input_line_pointer += 7;
  270.     s_data1();
  271.     return;
  272.     }
  273.     as_warn("Unknown segment type");
  274.     demand_empty_rest_of_line();
  275.     return;
  276. }
  277.  
  278. static void
  279. s_data1()
  280. {
  281.     subseg_new(SEG_DATA, 1);
  282.     demand_empty_rest_of_line();
  283.     return;
  284. }
  285.  
  286. static void
  287. s_proc()
  288. {
  289.     extern char is_end_of_line[];
  290.  
  291.     while (!is_end_of_line[*input_line_pointer]) {
  292.     ++input_line_pointer;
  293.     }
  294.     ++input_line_pointer;
  295.     return;
  296. }
  297.  
  298. /* This function is called once, at assembler startup time.  It should
  299.    set up all the tables, etc. that the MD part of the assembler will need.  */
  300. void
  301. md_begin()
  302. {
  303.   register char *retval = NULL;
  304.   int lose = 0;
  305.   register unsigned int i = 0;
  306.  
  307.   op_hash = hash_new();
  308.   if (op_hash == NULL)
  309.     as_fatal("Virtual memory exhausted");
  310.  
  311.   while (i < NUMOPCODES)
  312.     {
  313.       const char *name = sparc_opcodes[i].name;
  314.       retval = hash_insert(op_hash, name, &sparc_opcodes[i]);
  315.       if(retval != NULL && *retval != '\0')
  316.     {
  317.       fprintf (stderr, "internal error: can't hash `%s': %s\n",
  318.            sparc_opcodes[i].name, retval);
  319.       lose = 1;
  320.     }
  321.